from fastapi import APIRouter
from pydantic import BaseModel

import numpy as np
import pandas as pd
import os
from app.common.utils import get_current_datetime_str, DEST_DIR
import statsmodels.api as sm
from io import BytesIO
from typing import List
from fastapi.responses import StreamingResponse


router = APIRouter(prefix="/generating", tags=["data_generating"])

# MediationModel 和 ModerationModel：这些是用 Pydantic 定义的模型，表示中介和调节模型所需的参数。Pydantic 会自动验证请求的 JSON 数据，并将其转换为 Python 对象

# e_m 和 e_y：它们是模型中的随机误差项，用来表示因果关系之外的未解释部分，模拟现实中数据的不可预测性。
# sigma：它控制误差项的波动范围（标准差），从而影响数据的随机性和波动性。

# 中介参数
class MediationModel(BaseModel):
    a: float = 0.5
    b: float = 0.7
    c: float = 0.3
    sigma: float = 1.0
    n: int = 100  # 默认样本数
    min_x: float = 0  # 自变量 X 的最小值
    max_x: float = 200  # 自变量 X 的最大值
    is_integer: bool = False  # 控制 X 是否为整数

# 中介模型数据生成逻辑
def generate_mediation_data(n, a=0.5, b=0.7, c=0.3, sigma=1.0, min_x=0, max_x=10, is_integer=False):
    if is_integer:
        # 生成整数类型的 X
        X = np.random.randint(min_x, max_x + 1, size=n)
    else:
        # 生成浮动型的 X
        X = np.random.uniform(min_x, max_x, size=n)
    
    # 生成中介变量 M 和因变量 Y 的随机误差
    e_m = np.random.normal(scale=sigma, size=n)
    M = a * X + e_m  # 中介变量 M
    e_y = np.random.normal(scale=sigma, size=n)
    Y = b * M + c * X + e_y  # 因变量 Y
    
    return pd.DataFrame({'X': X, 'M': M, 'Y': Y})

# 调节参数
class ModerationModel(BaseModel):
    b: float = 0.5
    c: float = 0.4
    d: float = 0.2
    sigma: float = 1.0
    n: int = 100  # 默认样本数
    min_x: float = 0  # 自变量 X 的最小值
    max_x: float = 200  # 自变量 X 的最大值
    is_integer: bool = False  # 控制 X 是否为整数

# 调节模型数据生成逻辑
def generate_moderation_data(n, b=0.5, c=0.4, d=0.2, sigma=1.0, min_x=0, max_x=10, is_integer=False):
    if is_integer:
        # 生成整数类型的 X
        X = np.random.randint(min_x, max_x + 1, size=n)
    else:
        # 生成浮动型的 X
        X = np.random.uniform(min_x, max_x, size=n)
    W = np.random.normal(size=n)
    XW = X * W
    e_y = np.random.normal(scale=sigma, size=n)
    Y = b * X + c * W + d * XW + e_y
    return pd.DataFrame({'X': X, 'W': W, 'XW': XW, 'Y': Y})

# 结构方程模型参数
class SEMModel(BaseModel):
    mediator: str
    independent: str
    dependent: str
    sample_size: int

def generate_sem_data():
    return None
def get_full_path(Identifier):
    return os.path.join(
        DEST_DIR, Identifier + "_" + get_current_datetime_str() + ".csv"
    )


# 中介
@router.post("/mediation_data",description="自变量 X 通过中介变量 M 影响因变量 Y, $ M=aX+em​,Y=bM+cX+ey $​")
async def generate_mediation_data_endpoint(model: MediationModel):
    data = generate_mediation_data(model.n, model.a, model.b, model.c, model.sigma,model.min_x,model.max_x,model.is_integer)
    # 构建完整的文件名
    outputfile_full_path = get_full_path('mediation')
    data.to_csv(outputfile_full_path, index=False)
    return {"dataPath": outputfile_full_path}

# 调节
@router.post("/moderation_data",description="调节变量 W 影响 X 对 Y 的效应：  $$ Y=bX+cW+dXW+ey $$ ")
async def generate_moderation_data_endpoint(model: ModerationModel):    
    data = generate_moderation_data(model.n, model.b, model.c, model.d, model.sigma)
    # 构建完整的文件名
    outputfile_full_path = get_full_path('moderation')

    data.to_csv(outputfile_full_path, index=False)
    return {"dataPath": outputfile_full_path}


# 结构方程模型
@router.post("/sem_data",description="潜变量与观测变量之间的关系：$$ L1=b1X1+b2X2+el​1,Y=b3L1+ey​ $$ 可以用类似的方式通过多元正态分布生成。")
async def generate_sem_data_endpoint(model: SEMModel):

    # 构建完整的文件名
    outputfile_full_path = get_full_path('sem')

    data = generate_sem_data(model)

    data.to_excel(outputfile_full_path, index=False)

    return {"dataPath": outputfile_full_path}
